/*
 * Carlos: Gestion de citas
 * 
 */
package infb.actions;

import java.text.ParseException;
import javax.naming.NamingException;
import org.apache.struts.action.*;
import javax.servlet.http.*;
import infb.forms.*;
import infb.dao.*;
import infb.errores.*;
import infb.modelo.Citas;
import infb.modelo.Medicos;
import infb.modelo.Pacientes;
import infb.util.Paginador;
import java.lang.String;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import javax.ejb.*;
import javax.naming.Context;
import javax.naming.InitialContext;

public class GestionCitasAction extends Action {

    /*
     * Metodo interno destinado a la creacion de citas
     */
    private ActionForward crearCitas(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        try {
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");
            MedicosInterfaz iMedico = (MedicosInterfaz) contexto.lookup("MedicosEJB");

            HoraCitaForm formularioCita = (HoraCitaForm) form;


            String fechaCad = formularioCita.getFechaFinalizacion();
            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy");
            Date fechaFinalizacion = sdf.parse(fechaCad);
            String estado = "Pendiente";
            String observaciones = formularioCita.getObservaciones();
            String dniMedico = formularioCita.getMedico();
            String paciente = formularioCita.getPaciente();
            String horaFinalizacion = formularioCita.getHora();
            //   System.out.println("dniMedico="+dniMedico);
            Medicos medico = (Medicos) iMedico.find(dniMedico);
            Date hoy = new Date();
            Citas cita = new Citas(hoy, fechaFinalizacion, estado, observaciones, medico, paciente, horaFinalizacion);
            iCita.create(cita);

            return mapping.findForward("ok");
        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la cita: " + ne.getMessage());
        }


    }
    //Estructura necesario para el calendario entienda los dias "ocupados"

    private String crearFormatoCalendario(ArrayList<ArrayList> listaMeses) {
        String listaMesesFormateada = new String();
        listaMesesFormateada = "var SPECIAL_DAYS = {";
        for (int i = 0; i < listaMeses.size(); i++) {
            listaMesesFormateada = listaMesesFormateada.concat(String.valueOf(i) + ":" + listaMeses.get(i) + ",");
        }
        listaMesesFormateada = listaMesesFormateada.concat("12 :[]};");
        return listaMesesFormateada;
    }

    private ArrayList<ArrayList> calcularDiasOcupados(String medico) {
        ArrayList<ArrayList> listaMeses = new ArrayList(12);
        for (int i = 0; i < 12; i++) {
            listaMeses.add(new ArrayList());
        }
        ArrayList<String> listaDias = new ArrayList();
        try {
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");
            MedicosInterfaz iMedicos = (MedicosInterfaz) contexto.lookup("MedicosEJB");

            Date fecha = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy");
            StringBuilder fechaCad = new StringBuilder(sdf.format(fecha));

            int tope = iMedicos.find(medico).getHoraFinConsulta() - iMedicos.find(medico).getHoraInicioConsulta();
            tope *= 4;
            //  System.out.println("TOPE:"+tope);
            List<Date> listaFechas = iCita.diasOcupados(medico, tope, fechaCad.toString());
            //  System.out.println("fechas:"+listaFechas);
            List<Date> listaFechasForm = new ArrayList<Date>();
            for (int i = 0; i < listaFechas.size(); i++) {
                listaFechasForm.add((Date) ((List) listaFechas.get(i)).get(0));
            }

            SimpleDateFormat sdfDia = new SimpleDateFormat("dd");
            StringBuilder dia;
            SimpleDateFormat sdfMes = new SimpleDateFormat("MM");
            StringBuilder mes;

            for (Date diaOcupado : listaFechasForm) {
                dia = new StringBuilder(sdfDia.format(diaOcupado));
                mes = new StringBuilder(sdfMes.format(diaOcupado));
                listaDias = listaMeses.get(Integer.valueOf(mes.toString()) - 1);
                listaDias.add(String.valueOf(dia));
                listaMeses.set(Integer.valueOf(mes.toString()) - 1, listaDias);

            }

        } catch (NamingException e) {
        }
        return listaMeses;
    }

    private ActionForward pedirCitas(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        try {
            HttpSession sesion = peticion.getSession();
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");
            PacientesInterfaz iPaciente = (PacientesInterfaz) contexto.lookup("PacientesEJB");

           
            MedicosInterfaz iMedicos = (MedicosInterfaz) contexto.lookup("MedicosEJB");
            String perfil = (String) sesion.getAttribute("perfil");
            String dniMedico=null;
            if(perfil.equals("paciente")){
                 Pacientes paciente = (Pacientes) sesion.getAttribute("usuario");
                dniMedico=paciente.getMedico().getDni();
            }else{
                dniMedico=peticion.getParameter("medico");
            }
            Medicos ObjetoMedico = iMedicos.find(dniMedico);


            ArrayList<ArrayList> listaMeses = calcularDiasOcupados(dniMedico);
            String listaMesesFormateada = crearFormatoCalendario(listaMeses);
            String apellido = ObjetoMedico.getApellido1();


            sesion.setAttribute("apellido", apellido);
            peticion.setAttribute("listaOcupados", listaMeses);
            peticion.setAttribute("listaOcupadosFormateado", listaMesesFormateada);

        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar citas: " + ne.getMessage());
        }

        return mapping.findForward("ok");
    }
    /*
     * Metodo interno destinado a la modificacion de citas
     */

    private ActionForward prepararInsercion(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        try {
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");

        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la cita: " + ne.getMessage());
        }

        return mapping.findForward("ok");
    }

    private List<String> horasTotales(String dniMedico) {
        try {
            Context contexto = new InitialContext();
            MedicosInterfaz iMedico = (MedicosInterfaz) contexto.lookup("MedicosEJB");
            Medicos medico = iMedico.find(dniMedico);

            int ini = medico.getHoraInicioConsulta();
            int fin = medico.getHoraFinConsulta();

            ArrayList<String> horaTotales = new ArrayList<String>();
            for (int i = ini; i < fin; i++) {
                if(i<10){
                horaTotales.add("0".concat(String.valueOf(i)).concat(":").concat("00"));
                horaTotales.add("0".concat(String.valueOf(i)).concat(":").concat("15"));
                horaTotales.add("0".concat(String.valueOf(i)).concat(":").concat("30"));
                horaTotales.add("0".concat(String.valueOf(i)).concat(":").concat("45"));
                }else{
                horaTotales.add(String.valueOf(i).concat(":").concat("00"));
                horaTotales.add(String.valueOf(i).concat(":").concat("15"));
                horaTotales.add(String.valueOf(i).concat(":").concat("30"));
                horaTotales.add(String.valueOf(i).concat(":").concat("45"));
                }
            }
            return horaTotales;
        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la clase DAO MedicosInterfaz " + ne.getMessage());
        } catch (NumberFormatException nfe) {
            throw new GestionHospitalariaException("Error: El identificador del medico debe ser una cadena de caracteres " + nfe.getMessage());
        }

    }


    //accedemos a la BBDD y construimos la lista de las horas disponibles
    private List<String> horasDisponibles(String fechaCad, String dniMedico) throws ParseException {
        try {
            ArrayList<String> horas = new ArrayList();
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");

            List<String> horasTotales = horasTotales(dniMedico);
            List horasOcupadas = iCita.horasOcupadas(dniMedico, fechaCad);
            List<String> horasOcupadasForm = new ArrayList<String>();
            String aux;
            for (int i = 0; i < horasOcupadas.size(); i++) {
                horasOcupadasForm.add((String) ((List) horasOcupadas.get(i)).get(0));
            }
            horasTotales.removeAll(horasOcupadasForm);
            return horasTotales;
        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la cita: " + ne.getMessage());
        }
    }


    /*
     * Metodo interno destinado a la modificacion de citas
     */
    private ActionForward pedirHora(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        try {
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");
            MedicosInterfaz iMedicos = (MedicosInterfaz) contexto.lookup("MedicosEJB");

            HttpSession sesion = peticion.getSession();
            List<String> horas;
            String fecha = peticion.getParameter("fecha");
            String dniMedico = peticion.getParameter("medico");
            Medicos ObjetoMedico = iMedicos.find(dniMedico);

            horas = horasDisponibles(fecha, dniMedico);

            SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yy");
            Date fechaDate=sdf.parse(fecha);
            Date hoy=new Date();
            Boolean fechaValida=fechaDate.after(hoy);

            sesion.setAttribute("fechaValida", fechaValida);
            peticion.setAttribute("apellido", (String) ObjetoMedico.getApellido1());
            sesion.setAttribute("fechaCita", fecha);
            sesion.setAttribute("horas", horas);



        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la cita: " + ne.getMessage());
        }

        return mapping.findForward("ok");
    }

    /*
     * Metodo interno destinado a la eliminacion de medicos
     */
    private ActionForward eliminarCitas(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        try {
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");

        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la cita: " + ne.getMessage());
        }

        return mapping.findForward("ok");
    }

    /*
     * Metodo interno destinado a ver datos de una cita (no necesario)
     */
    private ActionForward verCitas(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        try {
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");

        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la cita: " + ne.getMessage());
        }

        return mapping.findForward("ok");
    }
    /*
     * Metodo interno destinado para pedir una cita a un especialista
     */
    private ActionForward pedirEspecialista(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {

        try {
            Context contexto = new InitialContext();
            MedicosInterfaz medicosInterfaz = (MedicosInterfaz) contexto.lookup("MedicosEJB");

            // Recuperamos la sesion del usuario
            HttpSession sesion = peticion.getSession();
            // Cargamos la lista de especialidades
            EspecialidadesInterfaz especialidadesInterfaz = (EspecialidadesInterfaz) contexto.lookup("EspecialidadesEJB");
            List listaEspecialidades = especialidadesInterfaz.findAll();
            sesion.setAttribute("listaEspecialidades", listaEspecialidades);

            String buscar = peticion.getParameter("buscar");
            if (buscar != null && buscar.equals("1")) {
                // Obtenemos los parametros de busqueda
                BuscarMedicosForm formularioBusqueda = (BuscarMedicosForm) form;
                String dni = formularioBusqueda.getDni();
                String numColegiado = formularioBusqueda.getNumColegiado();
                String apellido1 = formularioBusqueda.getApellido1();
                String apellido2 = formularioBusqueda.getApellido2();
                String nombre = formularioBusqueda.getNombre();
                String especialidad = formularioBusqueda.getEspecialidad();

                // Almacenamos el resultado de la consulta en la peticion
                Paginador p = new Paginador(medicosInterfaz.busquedaAvanzada(dni, numColegiado, apellido1, apellido2, nombre, especialidad), peticion);
                List listaMedicos = p.getResultadosPaginados();
                if (listaMedicos != null) {
                    peticion.setAttribute("lista_medicos", listaMedicos);
                    peticion.setAttribute("navegacion", p.getNavegacion());
                    peticion.setAttribute("informacion", p.getMetaInformacion());
                }
            }

            return mapping.findForward("ok");
        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la clase DAO MedicosInterfaz " + ne.getMessage());
        }


    }
    
//metodo auxiliar
    private <T> List<T> arrayToList(T[] array) {
        List lista = new ArrayList<T>();
        if (array != null) {
            for (int i = 0; i < array.length; i++) {
                lista.add(array[i]);
            }
        }
        return lista;
    }
    /*
     * Metodo interno destinado al listado citas
     */
    private ActionForward listarCitas(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        try {
            HttpSession sesion = peticion.getSession();
            String perfil = (String) sesion.getAttribute("perfil");
            Context contexto = new InitialContext();
            CitasInterfaz iCita = (CitasInterfaz) contexto.lookup("CitasEJB");
            ListarCitasForm formularioBusqueda=(ListarCitasForm)form;
            
            List listaCitas=null;
            List estado=this.arrayToList(formularioBusqueda.getEstado());

            if (perfil.equals("medico")) {
                Medicos medico = (Medicos) sesion.getAttribute("usuario");
                listaCitas = iCita.citasMedico(medico,estado);
   
            //recupero la lista d las citas del medico
            }else if (perfil.equals("paciente")) {
                //recupero la lista d las citas del paciente
                Pacientes paciente = (Pacientes) sesion.getAttribute("usuario");
                String unpaciente = paciente.getTarjetaSanitaria();
                listaCitas = iCita.citasPaciente(new String(unpaciente),estado);
            }

            Paginador p =new Paginador(listaCitas, peticion);
            listaCitas = p.getResultadosPaginados();
            peticion.setAttribute("lista_citas", listaCitas);
            peticion.setAttribute("navegacion", p.getNavegacion());
            peticion.setAttribute("informacion", p.getMetaInformacion());

        } catch (NamingException ne) {
            throw new GestionHospitalariaException("Error: No se pudo cargar la cita: " + ne.getMessage());
        }

        return mapping.findForward("listar_ok");
    }

    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest peticion, HttpServletResponse respuesta) throws GestionHospitalariaException, NamingException, ParseException {
        String delegaEn = mapping.getParameter();
        HttpSession sesion=peticion.getSession();
        if (delegaEn.equalsIgnoreCase("crear")) {
            // codigo para crear una cita
            return this.crearCitas(mapping, form, peticion, respuesta);
        } else if (delegaEn.equalsIgnoreCase("preparar_insercion")) {
            // modificar una cita
            return this.prepararInsercion(mapping, form, peticion, respuesta);
        } else if (delegaEn.equalsIgnoreCase("pedir")) {
            // modificar pedir una cita
            return this.pedirCitas(mapping, form, peticion, respuesta);
        } else if (delegaEn.equalsIgnoreCase("pedirHora")) {
            // modificar pedir la hora
            return this.pedirHora(mapping, form, peticion, respuesta);
        } else if (delegaEn.equalsIgnoreCase("eliminar")) {
            // borrar una cita
            return this.eliminarCitas(mapping, form, peticion, respuesta);
        } else if (delegaEn.equalsIgnoreCase("ver")) {
            // borrar ver una cita
            return this.verCitas(mapping, form, peticion, respuesta);
        } else if (delegaEn.equalsIgnoreCase("buscarEspecialista")) {
            // borrar un medicopedirEspecialista
            return this.pedirEspecialista(mapping, form, peticion, respuesta);                
        } else {
            return this.listarCitas(mapping, form, peticion, respuesta);
        }
    }
}
